package com.sfang.common.util.collection;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sfang.common.util.string.StringUtils;
import org.apache.commons.beanutils.BeanUtilsBean;
import org.apache.commons.collections.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.*;
import java.util.Map.Entry;

public class MapUtil {

    private static final Logger logger = LoggerFactory.getLogger(MapUtil.class);

    public static Map<String, String> convertTo(Map<String, Object> paras) {

        Map<String, String> targetMap = new HashedMap();

        try {
            for (Entry<String, Object> entry : paras.entrySet())
                try {
                    targetMap.put(entry.getKey(), entry.getValue() == null ? null : entry.getValue().toString());
                } catch (Exception e) {
                    logger.error(String.format("MapUtil 存放元素异常，key-%s value-%s", entry.getKey(), entry.getValue()));
                }
        } catch (Exception err) {
            logger.error(String.format("MapUtil 存放元素异常，原始map-%s", JSON.toJSONString(paras)));
        }
        return targetMap;
    }

    public static <T> List<T> deepCopy(List<T> src) {
        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(src);

            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in = new ObjectInputStream(byteIn);
            @SuppressWarnings("unchecked")
            List<T> dest = (List<T>) in.readObject();
            return dest;
        } catch (Exception e) {
            return null;
        }
    }

    public static Map<String, String> convertParametersToMap(String params) {

        Map<String, String> paramsSortMap = new TreeMap(
                new Comparator<String>() {
                    public int compare(String str1, String str2) {

                        return str1.compareTo(str2);
                    }
                });

        if (params != null) {
            String[] paramArray = params.split("&");
            for (String param : paramArray) {
                String[] entity = param.split("=");
                String key = entity[0];
                String value = entity[1];

                paramsSortMap.put(key, value);
            }
        }

        return paramsSortMap;
    }

    public static Map<String, String> convertParametersToMap(Map<String, String[]> parameterMap) {
        Map<String, String> tempMap = new HashMap<String, String>();
        Set<Entry<String, String[]>> set = parameterMap.entrySet();
        Iterator<Entry<String, String[]>> it = set.iterator();

        while (it.hasNext()) {
            Entry<String, String[]> entry = it.next();
            for (String str : entry.getValue()) {
                tempMap.put(entry.getKey(), str);
            }
        }

        return tempMap;
    }

    public static Map<String, Object> toMap(Object obj) {
        HashMap map = new HashMap();

        List<Field> allFields = new ArrayList<>();
        allFields.addAll(Arrays.asList(obj.getClass().getDeclaredFields()));

        if (obj.getClass().getSuperclass() != null)
            allFields.addAll(Arrays.asList(obj.getClass().getSuperclass().getDeclaredFields()));

        Field[] fields=new Field[allFields.size()];
        allFields.toArray(fields);

        Field[] arr$ = fields;
        int len$ = fields.length;

        for (int i$ = 0; i$ < len$; ++i$) {
            Field field = arr$[i$];

            try {
                Object fieldValue;
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                    fieldValue = field.get(obj);
                    field.setAccessible(false);
                } else {
                    fieldValue = field.get(obj);
                }

                if (fieldValue != null) {
                    if (fieldValue instanceof String) {
                        if (StringUtils.hasText((String) fieldValue)) {
                            map.put(field.getName(), (String) fieldValue);
                        }
                    } else {

                        if (fieldValue instanceof Date)
                            map.put(field.getName(), ((Date) fieldValue).getTime());
                        else
                            map.put(field.getName(), fieldValue);

                    }
                }
            } catch (IllegalArgumentException var9) {
                var9.printStackTrace();
            } catch (IllegalAccessException var10) {
                var10.printStackTrace();
            }
        }

        return map;
    }

    public static Map<String, Object> processMapDate(Map map) {

        Iterator<Entry<String, Object>> it = map.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, Object> entry = it.next();

            if (entry.getValue() instanceof Date)
                entry.setValue(((Date) entry.getValue()).getTime());
        }

        return map;
    }

    public static <T> T convertObject(Map<String, Object> map, Class<T> clazz) {
        try {

            if (map == null)
                return null;

            T t = clazz.newInstance();
            BeanUtilsBean.getInstance().getConvertUtils().register(false, false, 0);
            org.apache.commons.beanutils.BeanUtils.populate(t, map);
            return t;
        } catch (Exception e) {
            logger.error(String.format("map convertObject class-【%s】 data-【%s】 error:【%s】",
                    JSON.toJSONString(e),
                    JSON.toJSONString(map),
                    clazz));
            throw new RuntimeException(e);
        }
    }

    public static Map<String, String> convertTo(JSONObject jsonObject) {

        Map<String, String> map = new HashMap<>();

        Iterator it = jsonObject.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, Object> entry = (Entry<String, Object>) it.next();
            map.put(entry.getKey(), String.valueOf(entry.getValue()));
        }

        return map;

    }
}
